home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / ds5000.md / netDFRecv.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  20KB  |  657 lines

  1. /* 
  2.  * netDFRecv.c -
  3.  *
  4.  * Routines to manage the receive unit of the DEC FDDI controller 700.
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/ds5000.md/netDFRecv.c,v 1.3 92/09/29 16:39:06 jhh Exp $";
  19. #endif not lint
  20.  
  21. #include <sprite.h>
  22. #include <netDFInt.h>
  23. #include <vm.h>
  24. #include <vmMach.h>
  25. #include <sys.h>
  26. #include <list.h>
  27. #include <machMon.h>
  28. #include <dbg.h>
  29.  
  30. /*
  31.  * Macros to step HOST RCV ring pointers.
  32.  */
  33. #define    NEXT_HOST_RECV(p) ( (((p)+1) > statePtr->hostRcvLastDescPtr) ? \
  34.                 statePtr->hostRcvFirstDescPtr : \
  35.                 ((p)+1))
  36. /*
  37.  * Macros to step SMT RCV ring pointers.
  38.  */
  39. #define    NEXT_SMT_RECV(p) ( (((p)+1) > statePtr->smtRcvLastDescPtr) ? \
  40.                 statePtr->smtRcvFirstDescPtr : \
  41.                 ((p)+1))
  42. #define    PREV_SMT_RECV(p) ( (((p)-1) < statePtr->smtRcvFirstDescPtr) ? \
  43.                 statePtr->smtRcvLastDescPtr : \
  44.                 ((p)-1))
  45.  
  46. /*
  47.  * Macro to assign buffer addresses to HOST RCV descriptor fields
  48.  */
  49. #define ASSIGN_BUF_ADDR(ptr, bufAddr) \
  50. { \
  51.     register unsigned long _addr_; \
  52.  \
  53.     _addr_ = (unsigned long)(bufAddr); \
  54.     _addr_ = _addr_ >> 9; \
  55.     Bf_WordSet(((unsigned long *)ptr), 9, 23, _addr_) \
  56. }
  57.  
  58. /*
  59.  * Macro to test a descriptor to see if the adapter owns it.
  60.  */
  61. #define ADAPTER_RCV_OWN(ownWord) \
  62.     (((unsigned long)(ownWord) & NET_DF_OWN) == NET_DF_ADAPTER_OWN)
  63.  
  64. /*
  65.  * Macros to translate from RCV descriptors to the buffers
  66.  * that they are associated with.
  67.  */
  68. #ifdef NET_DF_USE_UNCACHED_MEM
  69. #define HostRcvBufFromDesc(statePtr, descPtr) \
  70.   (NetDFHostRcvBuf *)(statePtr->hostRcvFirstBufPtr + \
  71.    (unsigned long)(descPtr - statePtr->hostRcvFirstDescPtr))
  72. #else
  73. #define HostRcvBufFromDesc(statePtr, descPtr) \
  74.   (NetDFHostRcvBuf *)(statePtr->hostRcvBuffers[ \
  75.    (unsigned long)(descPtr - statePtr->hostRcvFirstDescPtr)])
  76. #endif
  77.  
  78. #define SmtRcvBufFromDesc(statePtr, descPtr) \
  79.   (NetDFSmtRcvBuf *)(statePtr->smtRcvFirstBufPtr + \
  80.    (unsigned long)(descPtr - statePtr->hostRcvFirstDescPtr))
  81.  
  82. /*
  83.  * For now use kernel initialized memory.  The buffers must start
  84.  * on a 512-byte boundary
  85.  */
  86. unsigned char hostRcvBufferMem[512 +
  87.        NET_DF_NUM_HOST_RCV_ENTRIES * NET_DF_HOST_RCV_BUF_SIZE];
  88.  
  89. /*
  90.  *----------------------------------------------------------------------
  91.  *
  92.  * AllocateRecvMem --
  93.  *
  94.  *    Allocate kernel memory for receive ring and data buffers.    
  95.  *
  96.  * Results:
  97.  *    None.
  98.  *
  99.  * Side effects:
  100.  *    Device state structure is updated.
  101.  *
  102.  *----------------------------------------------------------------------
  103.  */
  104. static void
  105. AllocateRecvMem(statePtr)
  106.     register NetDFState        *statePtr; /* The state of the interface. */
  107. {
  108.     register unsigned long    memBase;
  109.     register int                i;
  110.  
  111.     /*
  112.      * SMT RCV descriptor ring.
  113.      */
  114.     statePtr->smtRcvFirstDescPtr = (NetDFSmtRcvDesc *)
  115.     (statePtr->initComPtr->smtRcvBase + statePtr->slotAddr);
  116.  
  117.     /*
  118.      * HOST RCV descriptor ring.
  119.      */
  120.     statePtr->hostRcvFirstDescPtr = (NetDFHostRcvDesc *)
  121.     (statePtr->initComPtr->hostRcvBase + statePtr->slotAddr);
  122.  
  123. #ifdef NET_DF_USE_UNCACHED_MEM
  124.  
  125.     printf("DEC FDDI: Using uncached memory for receive buffers.\n");
  126.     /*
  127.      * Allocate the ring of receive buffer descriptors.  The ring must start
  128.      * on 512-byte boundary.  For now, use kernel initialized memory
  129.      * so that we don't have to worry about the effects of DMA.
  130.      */
  131.     memBase = (unsigned long) (&hostRcvBufferMem[0]);
  132.     /*
  133.      * Ensure that the ring starts on the 512-byte boundary.
  134.      */
  135.     if (memBase & 0x1FF) {
  136.     memBase = (memBase + 512) & ~0x1FF;
  137.     }
  138.     /*
  139.      * Use uncached unmapped addresses
  140.      */
  141.     memBase = (unsigned long)MACH_UNCACHED_ADDR(memBase);
  142.     statePtr->hostRcvFirstBufPtr = (volatile NetDFHostRcvBuf *) memBase;
  143.  
  144. #else /* NET_DF_USE_UNCACHED_MEM */
  145.  
  146.     printf("DEC FDDI: Using cached memory for receive buffers.\n");
  147.     for (i = 0; i < NET_DF_NUM_HOST_RCV_ENTRIES; i++) {
  148.     /*
  149.      * Ensure that the ring starts on the 512-byte boundary.
  150.      */
  151.     memBase = (unsigned long) malloc(NET_DF_HOST_RCV_BUF_SIZE + 512);
  152.     if (memBase & 0x1FF) {
  153.         memBase = (memBase + 512) & ~0x1FF;
  154.     }
  155.     memBase = memBase - MACH_KSEG2_ADDR + MACH_CACHED_MEMORY_ADDR;
  156.     statePtr->hostRcvBuffers[i] = (volatile NetDFHostRcvBuf *) memBase;
  157.     }
  158.     statePtr->hostRcvFirstBufPtr = statePtr->hostRcvBuffers[0];
  159.  
  160. #endif /* NET_DF_USE_UNCACHED_MEM */
  161.  
  162.     statePtr->recvMemAllocated = TRUE;
  163.     return;
  164. }
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * NetDFRecvInit --
  170.  *
  171.  *    Initialize the receive buffer lists for the receive unit allocating
  172.  *    memory if need.
  173.  *
  174.  * Results:
  175.  *    None.
  176.  *
  177.  * Side effects:
  178.  *    The receive ring is initialized and the device state structure is
  179.  *    updated.
  180.  *
  181.  *----------------------------------------------------------------------
  182.  */
  183.  
  184. void
  185. NetDFRecvInit(statePtr)
  186.     register NetDFState               *statePtr;  /* Interface state. */
  187. {
  188.     register volatile NetDFHostRcvDesc *descPtr; 
  189.     register volatile NetDFHostRcvBuf  *bufPtr;
  190.     register int                    bufNum;
  191.  
  192.     if (!statePtr->recvMemAllocated) {
  193.     AllocateRecvMem(statePtr);
  194.     }
  195.     /*
  196.      * Reset the HOST and SMT RCV ring pointers.
  197.      */
  198.     statePtr->hostRcvNextDescPtr = statePtr->hostRcvFirstDescPtr;
  199.     statePtr->hostRcvLastDescPtr = statePtr->hostRcvFirstDescPtr +
  200.     (NET_DF_NUM_HOST_RCV_ENTRIES - 1);
  201.  
  202. #ifdef NET_DF_USE_UNCACHED_MEM
  203.     statePtr->hostRcvNextBufPtr = statePtr->hostRcvFirstBufPtr;
  204.     statePtr->hostRcvLastBufPtr = statePtr->hostRcvFirstBufPtr +
  205.     (NET_DF_NUM_HOST_RCV_ENTRIES - 1);    
  206. #else
  207.     statePtr->hostRcvNextBufPtr = statePtr->hostRcvBuffers[0];
  208.     statePtr->hostRcvBufIndex = 0;
  209.     statePtr->hostRcvLastBufPtr = 
  210.     statePtr->hostRcvBuffers[NET_DF_NUM_HOST_RCV_ENTRIES - 1];
  211. #endif
  212.  
  213.     statePtr->smtRcvNextDescPtr = statePtr->smtRcvFirstDescPtr;
  214.     statePtr->smtRcvLastDescPtr = statePtr->smtRcvFirstDescPtr +
  215.     (statePtr->initComPtr->smtRcvEntries - 1);
  216.     /* 
  217.      * Initialize the Host RCV ring descriptors.
  218.      */
  219.     descPtr = statePtr->hostRcvFirstDescPtr;
  220.     for (bufNum = 0; bufNum < NET_DF_NUM_HOST_RCV_ENTRIES; 
  221.      bufNum++, descPtr++) { 
  222.     /*
  223.      * Point the descriptor at its buffer, and give it to the adapter.
  224.      */
  225. #ifdef NET_DF_USE_UNCACHED_MEM
  226.     bufPtr = statePtr->hostRcvFirstBufPtr + bufNum;
  227. #else
  228.     bufPtr = statePtr->hostRcvBuffers[bufNum];
  229. #endif    
  230.     ASSIGN_BUF_ADDR(&descPtr->bufAPtr, bufPtr->bufA);
  231.     ASSIGN_BUF_ADDR(&descPtr->bufBPtr, bufPtr->bufB);
  232.     descPtr->rmcRcvDesc = 0x0;
  233.     Bf_WordSet(((unsigned long *)&(descPtr->bufAPtr)), 0, 1, 0x0);
  234.     }
  235.     /*
  236.      * Initialize the SMT RCV ring descriptors.  Turns out that the
  237.      * descriptors already point to their buffers.
  238.      */
  239.     statePtr->lastRecvCnt = 0;
  240.     statePtr->recvMemInitialized = TRUE;
  241. }
  242.  
  243. /*
  244.  *----------------------------------------------------------------------
  245.  *
  246.  * HostRcvToSmtRcv --
  247.  *
  248.  *    Transfer an SMT packet from the HOST RCV ring to the SMT RCV ring.
  249.  *
  250.  * Results:
  251.  *    SUCCESS if the transfer was successful, and FAILURE otherwise.
  252.  *
  253.  * Side effects:
  254.  *    A packet is written to the SMT RCV ring on the adapter.
  255.  *
  256.  *----------------------------------------------------------------------
  257.  */
  258. static ReturnStatus
  259. HostRcvToSmtRcv(statePtr, hostDescPtr)
  260.     register NetDFState               *statePtr;
  261.     register NetDFHostRcvDesc         *hostDescPtr;
  262. {
  263.     register volatile NetDFSmtRcvDesc *smtDescPtr;
  264.     register volatile NetDFSmtRcvBuf  *smtBufPtr;
  265.     register NetDFHostRcvBuf          *hostBufPtr;
  266.     register unsigned long            length;
  267.  
  268.     smtDescPtr = statePtr->smtRcvNextDescPtr;
  269.     /*
  270.      * Do some sanity checks.
  271.      */
  272.     if (ADAPTER_RCV_OWN(smtDescPtr->own)) {
  273.     printf("DEC FDDI: SMT RCV descriptor owned by adapter.\n");
  274.     return (FAILURE);
  275.     }
  276.     smtBufPtr = (NetDFSmtRcvBuf *)
  277.     (statePtr->slotAddr + (unsigned long)(smtDescPtr->bufAddr));
  278.     hostBufPtr = HostRcvBufFromDesc(statePtr, hostDescPtr);
  279.     /*
  280.      * Transfer the data.  Even though the host buffers are split
  281.      * into two, we allocated them contiguously so we can just
  282.      * copy them in one fell swoop.
  283.      */
  284.     smtDescPtr->rmcRcvDesc = hostDescPtr->rmcRcvDesc;
  285.     length = hostDescPtr->rmcRcvDesc & NET_DF_RMC_RCV_PBC;
  286.     /*
  287.      * According to the description of the RMC RCV Descriptor,
  288.      * the PBC does not include the three Packet Request Header (PRH)
  289.      * bytes found in the first word of the buffer.  So we must
  290.      * take those into account while copying from the HOST RCV
  291.      * buffer to the SMT RCV buffer.
  292.      */
  293.     length += 3;
  294.     NetDFBcopy((char *)hostBufPtr, (char *)smtBufPtr, length);
  295.     /*
  296.      * Give the SMT RCV descriptor and buffer to the adapter, and
  297.      * poke the magic bit.
  298.      */
  299.     smtDescPtr->own = NET_DF_ADAPTER_OWN;
  300.     *(statePtr->regCtrlA) |= NET_DF_CTRLA_SMT_RCV_POLL_DEMAND;
  301.     Mach_EmptyWriteBuffer();
  302.     
  303.     statePtr->smtRcvNextDescPtr = NEXT_SMT_RECV(smtDescPtr);
  304.     return(SUCCESS);
  305. }
  306.  
  307. /*
  308.  *----------------------------------------------------------------------
  309.  *
  310.  * GotAPacket --
  311.  *
  312.  *    Determine what to do with the given packet:  if the packet
  313.  *      is an SMT packet, then transfer it to the SMT RCV ring;
  314.  *      if the packet is a host LLC packet, give it to the
  315.  *      proper authorities.
  316.  *
  317.  * Results:
  318.  *    None.
  319.  *
  320.  * Side effects:
  321.  *    A packet may be written to the SMT RCV ring on the adapter.
  322.  *
  323.  *----------------------------------------------------------------------
  324.  */
  325. static void
  326. GotAPacket(statePtr, descPtr, bufPtr)
  327.     register NetDFState       *statePtr;
  328.     register NetDFHostRcvDesc *descPtr;
  329.     NetDFHostRcvBuf           *bufPtr;
  330. {
  331.     register unsigned char    *dataPtr;
  332.     register int              size;
  333.     register ReturnStatus     result;
  334.  
  335.     dataPtr = (unsigned char *)bufPtr;
  336.  
  337.     if (dataPtr[3] == NET_DF_FRAME_SMT ||
  338.     dataPtr[3] == NET_DF_FRAME_SMT_INFO ||
  339.     dataPtr[3] == NET_DF_FRAME_SMT_NSA) {
  340.  
  341.     MAKE_NOTE("Received an SMT packet.");
  342.     result = HostRcvToSmtRcv(statePtr, descPtr);
  343.     if (result != SUCCESS) {
  344.         printf("DEC FDDI: Failed to transfer from HOST to SMT RCV.\n");
  345.     } else {    
  346.         MAKE_NOTE("processed SMT RCV packet successfully.");
  347.         DFprintf("DEC FDDI: Transfer from HOST to SMT RCV succeeded.\n");
  348.     }
  349.     return;
  350.     }
  351.     if (dataPtr[3] != NET_FDDI_SPRITE) {
  352.     /*
  353.      * This is not a Sprite FDDI packet, so just drop it on the floor.
  354.      */
  355.     return;
  356.     }
  357.     size = (int)(descPtr->rmcRcvDesc & NET_DF_RMC_RCV_PBC);
  358.     /*
  359.      * The size reported is not entirely correct.  The RMC RCV descriptor
  360.      * determines size by counting the 1 Frame Control byte, 4 CRC bytes,
  361.      * and the data bytes, ignoring the 3 Packet Request Header bytes. 
  362.      * We determine size by counting the Frame Control, PRH, and data bytes,
  363.      * ignoring the CRC bytes.  To adjust accordingly, we subtract one from
  364.      * the reported length.
  365.      */
  366.     size--;
  367.     MAKE_NOTE("received a HOST packet.");
  368.     Net_Input(statePtr->interPtr, dataPtr, size);
  369. }
  370.  
  371. /*
  372.  *----------------------------------------------------------------------
  373.  *
  374.  * CheckRmcRcvDesc --
  375.  *
  376.  *      Check the RMC RCV Descriptor of the given packet for
  377.  *      various transmission errors.
  378.  *
  379.  * Results:
  380.  *    SUCCESS if the packet is `OK', and FAILURE otherwise.
  381.  *
  382.  * Side effects:
  383.  *    If the packet has a problem, that problem is printed.
  384.  *
  385.  *----------------------------------------------------------------------
  386.  */
  387. static ReturnStatus
  388. CheckRmcRcvDesc(statePtr, descPtr)
  389.     NetDFState             *statePtr; /* State of the interface */
  390.     NetDFHostRcvDesc       *descPtr;  /* Descriptor pointing to packet. */
  391. {
  392.     register unsigned long bad;
  393.     register unsigned long pbc;
  394.     register unsigned long crc;
  395.     register unsigned long rrr;
  396.     register unsigned long dd;
  397.     register unsigned long ss;
  398.     register unsigned long fsc;
  399.     register unsigned long fsb;
  400.     register unsigned char frameControl;
  401.     NetDFHostRcvBuf        *bufPtr;
  402.     
  403.     bad = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_BAD;
  404.     pbc = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_PBC;
  405.  
  406.     if (bad) {
  407.     /*
  408.      * We've got ourselves here what they call a `bad' little packet.
  409.      */
  410.     fsc = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_FSC;
  411.     fsb = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_FSB;
  412.     crc = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_CRC;
  413.     rrr = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_RRR;
  414.     dd = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_DD;
  415.     ss = descPtr->rmcRcvDesc & NET_DF_RMC_RCV_SS;
  416.     if (crc && rrr == NET_DF_RRR_DADDR_UNMATCH && dd == NET_DF_DD_CAM &&
  417.         ss == NET_DF_SS_ALIAS) {
  418.         if (pbc == 8190 || pbc == 8191) {
  419.         printf("DEC FDDI: Received frame that was too long.\n");
  420.         } else {
  421.         printf("DEC FDDI: Fifo overflow with an interrupt.\n");
  422.         }
  423.     } else if (crc && rrr == NET_DF_RRR_DADDR_UNMATCH &&
  424.            dd == NET_DF_DD_CAM && ss == NET_DF_SS_CAM) {
  425.         printf("DEC FDDI: RMC/MAC interface error.\n");
  426.     } else if (rrr == NET_DF_RRR_SADDR_MATCH ||
  427.            rrr == NET_DF_RRR_DADDR_UNMATCH ||
  428.            rrr == NET_DF_RRR_RMC_ABORT) {
  429.         printf("DEC FDDI: Nasty hardware problem.\n");
  430.     } else if (rrr == NET_DF_RRR_INV_LENGTH) {
  431.         printf("DEC FDDI: Large frame with odd # of symbols.\n");
  432.     } else if (rrr == NET_DF_RRR_FRAGMENT) {
  433.         printf("DEC FDDI: Fragment error.\n");
  434.     } else if (rrr == NET_DF_RRR_FORMAT_ERROR) {
  435.         printf("DEC FDDI: Format error.\n");
  436.     } else if (rrr == NET_DF_RRR_MAC_RESET) {
  437.         printf("DEC FDDI: MAC reset error.\n");
  438.     } else {
  439.         if (crc) {
  440.         printf("DEC FDDI: Received packet with CRC error.\n");
  441.         } else if (!fsc && fsb) {
  442.         printf("DEC FDDI: Frame status error.\n");
  443.         } else {
  444.         printf("DEC FDDI: Large secondary NSA frame.\n");
  445.         }
  446.     }
  447.     return FAILURE;
  448.     } else {
  449.     bufPtr = HostRcvBufFromDesc(statePtr, descPtr);
  450.     frameControl = ((unsigned char *)bufPtr)[3];
  451.     switch(frameControl) {
  452.     case NET_DF_FRAME_SMT_INFO:
  453.     case NET_DF_FRAME_SMT_NSA:
  454.     case NET_DF_FRAME_SMT:
  455.         if (pbc < NET_DF_MIN_SMT_PACKET_SIZE ||
  456.         pbc > NET_DF_MAX_PACKET_SIZE) {
  457.         printf("DEC FDDI: SMT packet too long or too short ");
  458.         printf("(length = %d)\n", pbc);
  459.         return FAILURE;
  460.         }
  461.         break;
  462.     case NET_DF_FRAME_LLC_ASYNC:
  463.     case NET_DF_FRAME_LLC_SYNC:
  464.     case NET_DF_FRAME_HOST_LLC:
  465.     case NET_FDDI_SPRITE:
  466.         /*
  467.          * We subtract one because the PBC is slightly off for our
  468.          * interpretations.  See the note in GotAPacket.
  469.          */
  470.         if (pbc < NET_DF_MIN_LLC_PACKET_SIZE ||
  471.         ((pbc - 1) > NET_DF_MAX_PACKET_SIZE)) {
  472.         printf("DEC FDDI: LLC packet too long or too short ");
  473.         printf("(length = %d)\n", pbc);
  474.         return FAILURE;
  475.         }
  476.         break;
  477.     case NET_DF_FRAME_MAC_BEACON:
  478.     case NET_DF_FRAME_MAC_CLAIM:
  479.     case NET_DF_FRAME_MAC:
  480.         if (pbc < NET_DF_MIN_MAC_PACKET_SIZE ||
  481.         pbc > NET_DF_MAX_PACKET_SIZE) {
  482.         printf("DEC FDDI: MAC packet too long or too short ");
  483.         printf("(length = %d)\n", pbc);
  484.         return FAILURE;
  485.         }
  486.         break;
  487.     case NET_DF_FRAME_IMP_ASYNC:
  488.     case NET_DF_FRAME_IMP_SYNC:
  489.         if (pbc < NET_DF_MIN_IMP_PACKET_SIZE ||
  490.         pbc > NET_DF_MAX_PACKET_SIZE) {
  491.         printf("DEC FDDI: IMP packet too long or too short ");
  492.         printf("(length = %d)\n", pbc);
  493.         return FAILURE;
  494.         }
  495.         break;
  496.     case NET_DF_FRAME_NON_REST_TOK:
  497. /*    case NET_DF_FRAME_REST_TOK:  == MAC */
  498.         if (pbc < NET_DF_MIN_RES_PACKET_SIZE ||
  499.         pbc > NET_DF_MAX_PACKET_SIZE) {
  500.         printf("DEC FDDI: RES packet too long or too short ");
  501.         printf("(length = %d)\n", pbc);
  502.         return FAILURE;
  503.         }
  504.         break;
  505.     default:
  506.         break;
  507.     }
  508.     DFprintf("DEC FDDI: Frame Control %d\tPBC = %d\n", frameControl, pbc);
  509.     }
  510.     return SUCCESS;
  511. }
  512.  
  513. /*
  514.  *----------------------------------------------------------------------
  515.  *
  516.  * NetDFRecvProcess --
  517.  *
  518.  *    Process a newly received packet.
  519.  *
  520.  * Results:
  521.  *    FAILURE if something went wrong, SUCCESS otherwise.
  522.  *
  523.  * Side effects:
  524.  *    None.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528. ReturnStatus
  529. NetDFRecvProcess(dropPackets, statePtr)
  530.     Boolean                        dropPackets; /* Drop all packets. */
  531.     register NetDFState                *statePtr;   /* Interface state. */
  532. {
  533.     register volatile NetDFHostRcvDesc  *hostDescPtr;
  534.     register volatile NetDFHostRcvBuf   *bufPtr;
  535.     register Net_FDDIStats              *stats;
  536.     register int            size;
  537.     Boolean                tossPacket;
  538.     ReturnStatus                        result;
  539.  
  540.     /*
  541.      * If we are not initialized then forget the interrupt.
  542.      */
  543.     if (!statePtr->recvMemInitialized) {
  544.     return (FAILURE);
  545.     }
  546.  
  547.     hostDescPtr = statePtr->hostRcvNextDescPtr;
  548.     if (ADAPTER_RCV_OWN(hostDescPtr->bufAPtr)) {
  549.     /*
  550.      * I'm not quite sure why this is here.  But oh well.
  551.      *
  552.      * I think that I see why, now.  The problem is that we process
  553.      * multiple receive packets per receive interrupt.  Before we
  554.      * process the receive packets, however, we clear that interrupt.
  555.      * Packets may arrive, however, setting the interrupt again while we
  556.      * process those packets under the interrupt of an earlier packet.
  557.      * This leaves a hanging interrupt that signals something we've
  558.      * already done, and we have to check for it.
  559.      */
  560.     if (statePtr->lastRecvCnt == 0) {
  561.         printf("DEC FDDI: Really bogus receive interrupt. ");
  562.         printf("Buffer 0x%x owned by the adapter.\n", hostDescPtr);
  563.         return (FAILURE);
  564.     } else {
  565.         statePtr->lastRecvCnt = 0;
  566.         return (SUCCESS);
  567.     }
  568.     }
  569.     if (!(hostDescPtr->rmcRcvDesc & NET_DF_RMC_RCV_SOP)) {
  570.     printf("DEC FDDI: Really bogus receive interrupt. ");
  571.     printf("Buffer 0x%x doesn't start packet.\n", hostDescPtr);
  572.     return (FAILURE);
  573.     }
  574.  
  575.     tossPacket = dropPackets;
  576.     statePtr->lastRecvCnt = 0;
  577.     stats = &statePtr->stats;
  578.     while (TRUE) {
  579.     /* 
  580.      * Check to see if we have processed all our buffers. 
  581.      */
  582.     if (ADAPTER_RCV_OWN(hostDescPtr->bufAPtr)) {
  583.         break;
  584.     }
  585.     /*
  586.      * Each buffer pair is large enough to hold a MAX packet,
  587.      * so the START_OF_PACKET should always be set.
  588.      */
  589.     if (!(hostDescPtr->rmcRcvDesc & NET_DF_RMC_RCV_SOP)) {
  590.         printf("DEC FDDI: Really bogus receive interrupt. ");
  591.         printf("Buffer 0x%x doesn't start packet.\n", hostDescPtr);
  592.         return (FAILURE);
  593.     }
  594.     /*
  595.      * If the END_OF_PACKET bit is set, then the buffer has less than
  596.      * 512 bytes in it.  Only useful for statistical information.
  597.      */
  598.  
  599.     bufPtr = HostRcvBufFromDesc(statePtr, hostDescPtr);
  600. #ifndef NET_DF_USE_UNCACHED_MEM    
  601.     Mach_FlushCacheRange(bufPtr, 
  602.          (hostDescPtr->rmcRcvDesc & NET_DF_RMC_RCV_PBC) + 3);
  603. #endif
  604.     /*
  605.      * Check to make sure that the packet is valid:
  606.      * "A valid packet must be void of data corruption, must be of
  607.      * a certain frame type, and for each frame type must be of
  608.      * acceptable size." -- Need I say more?
  609.      */
  610.     result = CheckRmcRcvDesc(statePtr, hostDescPtr);
  611.     if (result != SUCCESS) {
  612.         tossPacket = TRUE;
  613.     }
  614.     /*
  615.      * Call a higher level protocol to process the packet.
  616.      */
  617.     if (!tossPacket) {
  618.         stats->packetsReceived++;
  619.         size = hostDescPtr->rmcRcvDesc & NET_DF_RMC_RCV_PBC;
  620.         stats->bytesReceived += size;
  621.         stats->receiveHistogram[size >> NET_FDDI_STATS_HISTO_SHIFT]++;
  622.         GotAPacket(statePtr, hostDescPtr, bufPtr); 
  623.     }
  624.     /*
  625.      * The adapter trashes the buffer address when it gives
  626.      * ownership of the descriptor back to the host.  We must
  627.      * update it here, and give ownership to the chip.
  628.      */
  629.     ASSIGN_BUF_ADDR(&hostDescPtr->bufAPtr, bufPtr->bufA)
  630.     ASSIGN_BUF_ADDR(&hostDescPtr->bufBPtr, bufPtr->bufB);
  631.     hostDescPtr->rmcRcvDesc = 0x0;
  632.     Bf_WordSet((unsigned long *)&hostDescPtr->bufAPtr, 0, 1, 0x0);
  633.  
  634.     statePtr->lastRecvCnt++;
  635.     /* 
  636.      * Check to see if we have processed all of our buffers. 
  637.      */
  638.     hostDescPtr = NEXT_HOST_RECV(hostDescPtr);
  639.     if (ADAPTER_RCV_OWN(hostDescPtr->bufAPtr)) {
  640.         break;
  641.     }
  642.     if (hostDescPtr == statePtr->hostRcvNextDescPtr) {
  643.         break;
  644.     }
  645.     }
  646.     stats->receiveReaped[statePtr->lastRecvCnt - 1]++;
  647.     /*
  648.      * Update the the ring pointer. We should be pointing at 
  649.      * the next buffer in which the adapter will place a packet.
  650.      */
  651.     statePtr->hostRcvNextDescPtr = hostDescPtr;
  652.     /*
  653.      * return a SUCCESS.
  654.      */
  655.     return (SUCCESS);
  656. }
  657.